/**
    \file GBK_to_unicode.c

    COPYRIGHT(C) 2011,ShenZhen smit CO.,LTD. \n
    All rights reserved. \n\n

    \brief implement the charset interface.

    \details charset interface includes:
        -
    \version 1.1
    \date 2014-09-13
    \author zhsu
    \note Created
    
*/

/* Includes --------------------------------------------------------------- */

#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include "GBK_to_unicode.h"

static int uni2char(const unsigned short uni, unsigned char *out, int boundlen)
{
	const unsigned char *uni2charset;
	unsigned char cl = uni&0xFF;
	unsigned char ch = (uni>>8)&0xFF;
	unsigned char out0,out1;

	if (boundlen <= 0)
		return -1;

	if (uni == 0x20ac) {/* Euro symbol.The only exception with a non-ascii unicode */
		out[0] = 0x80;
		return 1;
	}

	if (ch == 0) { /* handle the U00 plane*/
		/* if (cl == 0) return -EINVAL;*/ /*U0000 is legal in cp936*/
		out0 = u2c_00[cl*2];
		out1 = u2c_00[cl*2+1];
		if (out0 == 0x00 && out1 == 0x00) {
			if (cl<0x80) {
				out[0] = cl;
				return 1;
			}
			return -1;
		} else {
			if (boundlen <= 1)
				return -1;
			out[0] = out0;
			out[1] = out1;
			return 2;
		}
	}

	uni2charset = page_uni2charset[ch];
	if (uni2charset) {
		if (boundlen <= 1)
			return -1;
		out[0] = uni2charset[cl*2];
		out[1] = uni2charset[cl*2+1];
		if (out[0] == 0x00 && out[1] == 0x00)
			return -1;
		return 2;
	}
	else
		return -1;
}

int char2uni(const unsigned char *rawstring, int boundlen, unsigned short *uni)
{
	unsigned char ch, cl;
	const unsigned short *charset2uni;
	int n;

	if (boundlen <= 0)
		return -1;

	if (boundlen == 1) {
		if (rawstring[0]==0x80) { /* Euro symbol.The only exception with a non-ascii unicode */
			*uni = 0x20ac;
		} else {
			*uni = rawstring[0];
		}
		return 1;
	}

	ch = rawstring[0];
	cl = rawstring[1];

	charset2uni = page_charset2uni[ch];
	if (charset2uni && cl) {
		*uni = charset2uni[cl];
		if (*uni == 0x0000)
			return -1;
		n = 2;
	} else{
		if (ch==0x80) {/* Euro symbol.The only exception with a non-ascii unicode */
			*uni = 0x20ac;
		} else {
			*uni = ch;
		}
		n = 1;
	}
	return n;
}

int USM_CS_GBK2Unicode(unsigned short *pwszDest, const unsigned char* pszSrc, int nLength)
{
	unsigned short nUniCode;
	int nOffsetSrcBuf = 0;
	int nOffsetDestBuf = 0;
	
	if (nLength == 0)
	{
		*pwszDest = '\0';
		return(-1);
	}

	while (nOffsetSrcBuf < nLength)
	{
		if (!((*(pszSrc + nOffsetSrcBuf )) & 0x80))
		{
			*(pwszDest + nOffsetDestBuf) = *(pszSrc + nOffsetSrcBuf ) ;
			nOffsetSrcBuf += 1;
		}
		else
		{
			//nUniCode = GetGb2UniIndex((unsigned char *)(pszSrc + nOffsetSrcBuf));
			char2uni((unsigned char *)(pszSrc + nOffsetSrcBuf), 2, &nUniCode);
			*(pwszDest + nOffsetDestBuf)  = nUniCode;
			nOffsetSrcBuf += 2;
		}

		nOffsetDestBuf += 1;
	}
	*(pwszDest + nOffsetDestBuf)  = 0x00;
	
	return(0);
	
}


